#ifndef GNSTREAM_H
#define GNSTREAM_H

#include <GnFile.h>
#include <GnTArray.h>
#include <GnMemoryObject.h>
#include <GnTStreamTypeTraits.h>


class GnBinaryStream;
class GnAcsiiStream;
class GnObject;

class GNMAIN_ENTRY GnStream : public GnMemoryObject
{
public:
	typedef GnObject* (*CreateFunction)(const gchar**, gtuint);

public:

	class GnStreamObjects : public GnMemoryObject
	{
	private:
		GnObject* m_spObject;
	};

public:
	GnStream(void);
	virtual	~GnStream(void);

	bool Load( const gtchar* pFileName );
	bool LoadBinaryStream( GnBinaryStream* pFile );
	static void RegisterLoader(const gchar* pClassName, CreateFunction pfnFunc);
	static void UnregisterLoader(const gchar* pClassName);

	template< typename T >
	inline void GnStreamLoadBinary(T& obj);
	inline void GnStreamLoadBinary(void* pBuffer, gsize size);

	template< typename T >
	inline void GnStreamSaveBinary( T& obj );
	inline void GnStreamSaveBinary(const void * pBuffer, gsize size);

protected:
	template< typename T >
	void GnStreamLoadBinary( T& obj, GnT::_FalseType );
	template< typename T >
	void GnStreamLoadBinary( T& obj, GnT::_TrueType );
	template< typename T >
	void GnStreamSaveBinary( T& obj, GnT::_FalseType );
	template< typename T >
	void GnStreamSaveBinary( T& obj, GnT::_TrueType );

protected:
	GnFile* mpFile;
	GnTObjectArray<GnStreamObjects> mObjects;
	static std::map<const gchar*, CreateFunction> mCreateFunctions;
};

#include "GnStream.inl"

#endif // GNSTREAM_H